package com.xhj.bigfactory.bigFactory.Lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * -
 *
 * @author 周沫 @Date 2021-08-01 @Time 2:13
 */
public class DeadLockDemo {

  private static class Data {

    Lock lock1 = new ReentrantLock();

    Lock lock2 = new ReentrantLock();

    public void aLB() {
      synchronized (lock1) {
        System.out.println("a has lock1, and want lock2...");
        synchronized (lock2) {
          while (true) {}
        }
      }
    }

    public void bLA() {
      synchronized (lock2) {
        System.out.println("b has lock2, and want lock1...");
        synchronized (lock1) {
          while (true) {}
        }
      }
    }
  }

  private static class Data2 {

    Lock lock1 = new ReentrantLock();

    Lock lock2 = new ReentrantLock();

    public void aLB() {
      synchronized (lock1) {
        System.out.println("a has lock1, and want lock2...");
        synchronized (lock2) {
          System.out.println("waiting for lock2...");
        }
      }
    }

    public void bLA() {
      synchronized (lock2) {
        System.out.println("b has lock2, and want lock1...");
        synchronized (lock1) {
          System.out.println("waiting for lock1...");
        }
      }
    }
  }

  private static class Data3 {

    String str1 = "qwer";

    String str2 = "asdf";

    public void aLB() {
      synchronized (str1) {
        System.out.println("a has lock1, and want lock2...");
        synchronized (str2) {
          System.out.println("waiting for lock2...");
        }
      }
    }

    public void bLA() {
      synchronized (str2) {
        System.out.println("b has lock2, and want lock1...");
        synchronized (str1) {
          System.out.println("waiting for lock1...");
        }
      }
    }
  }

  private static class Data4 implements Runnable {

    String str1 = "qwer";

    String str2 = "asdf";

    @Override
    public void run() {
      synchronized (str1) {
        System.out.println("a has lock1, and want lock2...");
        synchronized (str2) {
          System.out.println("waiting for lock2...");
        }
      }
    }

    Data4(String str1, String str2) {
      synchronized (str1) {
        System.out.println("a has lock1, and want lock2...");
        synchronized (str2) {
          System.out.println("waiting for lock2...");
        }
      }
    }
  }

  private static class Data5 implements Runnable {

    Lock lock1 = new ReentrantLock();

    Lock lock2 = new ReentrantLock();

    public void aLB() {
      synchronized (lock1) {
        //				try {Thread.sleep(200);} catch (Exception e) {e.printStackTrace();}finally{}
        long s = 1L;
        for (long i = 0; i < 1000000L; i++) {
          s = s * i;
        }
        System.out.println("a has lock1, and want lock2...");
        synchronized (lock2) {
          while (true) {}
        }
      }
    }

    public void bLA() {
      synchronized (lock2) {
        //				try {Thread.sleep(200);} catch (Exception e) {e.printStackTrace();}finally{}
        System.out.println("b has lock2, and want lock1...");
        synchronized (lock1) {
          while (true) {}
        }
      }
    }

    @Override
    public void run() {}
  }

  public static void main(String[] args) {
    //		Data3 data = new Data3();
    //		new Thread(() -> {
    //			System.out.println(Thread.currentThread().getName() + ": come in...");
    //			data.aLB();
    //		}, "AAA").start();
    //		new Thread(() -> {
    //			System.out.println(Thread.currentThread().getName() + ": come in...");
    //			data.bLA();
    //		}, "BBB").start();
    //
    //		String str1="qwer";
    //		String str2="asdf";
    //		new Thread(new Data4(str1,str2), "AAA").start();
    //		new Thread(new Data4(str1,str2), "BBB").start();

    Data5 data = new Data5();
    new Thread(
            () -> {
              System.out.println(Thread.currentThread().getName() + ": come in...");
              data.aLB();
            },
            "AAA")
        .start();
    new Thread(
            () -> {
              System.out.println(Thread.currentThread().getName() + ": come in...");
              data.bLA();
            },
            "BBB")
        .start();
  }
}
